#include <stdio.h>
#include "system_init.h"
#include "can_driver.h"
#include "kf32a156_can.h"
#include "can_uds.h"
static uint32_t  Filter_Group_Address[2] = {0x40002890,0x40002900};

/*
 * Filter group type:
 *			- Acceptance code
 *			- Mask code
 *			- Frame type ��Standard Frame
 *			               Extended Frame
 */
Filter_Group_Typedef Filter_Group[2] = {
										{PHY_ADDR_ID,0x00000000,(MSG_ID_TYPE==0)?Standard_Frame:Extended_Frame},
										{FUN_ADDR_ID,0x00000000,(MSG_ID_TYPE==0)?Standard_Frame:Extended_Frame},
									   };

/*
 * CAN configuration information:
 *			- Enable CAN
 *			- CAN mode configuration
 *          - CAN worksource configuration
 *			- Can baud rate default value is 0
 *			- CAN synchronous jump width is 1
 *			- CAN time interval 1 is 10
 *			- CAN time interval 2 is 3
 *			- CAN bus acquisition times is 3 times
 */
CAN_InitTypeDef CAN_Condition = {
									TRUE,
									CAN_MODE_NORMAL,
									CAN_SOURCE_HFCLK_DIV_2,
#if(BAUDRATE == BAUDRATE100K)
									4,
#elif(BAUDRATE == BAUDRATE250K)
									1,
#elif(BAUDRATE == BAUDRATE500K)
									0,
#endif
									1,
									11,
									2,
									CAN_BUS_SAMPLE_3_TIMES,
									&Filter_Group[0]
								};

/*
 *   Can interrupt type:
 *			- Enable CAN transmit interrupt type
 *			- Enable CAN receive interrupt type
 *          - Enable CAN overflow interrupt type
 *          - Enable CAN buserror interrupt type
 *          - Enable CAN busoff interrupt type
 *          - Enable CAN error negative interrupt type
 */
Can_Interrupt_Type Can_Interrupt = {
									INTERRUPT_DISABLE,
									INTERRUPT_ENABLE,
									INTERRUPT_DISABLE,
									INTERRUPT_ENABLE,
									INTERRUPT_ENABLE,
									INTERRUPT_DISABLE,
									};

/*******************************************************************************
**                     		   Global Functions 		             	      **
*******************************************************************************/
/**
 *  @brief :
 *  @param in :None
 *  @param out :None
 *  @retval :None
 */
void CAN_Gpio_Init(void)
{
	//PC10=CAN4TX,PC11=CNA4RX
	GPIO_Pull_Up_Enable(GPIOC_SFR, GPIO_PIN_MASK_10 | GPIO_PIN_MASK_11, TRUE);
	GPIO_Write_Mode_Bits(GPIOC_SFR, GPIO_PIN_MASK_10 | GPIO_PIN_MASK_11, GPIO_MODE_RMP);

	GPIO_Pin_RMP_Config(GPIOC_SFR, GPIO_Pin_Num_10, GPIO_RMP_AF6);
	GPIO_Pin_RMP_Config(GPIOC_SFR, GPIO_Pin_Num_11, GPIO_RMP_AF6);
}

void CAN_Init(CAN_SFRmap* CANx, CAN_InitTypeDef* canInitStruct)
{
	CAN_Reset(CANx);
	uint32_t tmpreg = 0;

	/* ����У�� */
	CHECK_RESTRICTION(CHECK_CAN_ALL_PERIPH(CANx));
	CHECK_RESTRICTION(CHECK_FUNCTIONAL_STATE(canInitStruct->m_Enable));
	CHECK_RESTRICTION(CHECK_CAN_WORK_MODE(canInitStruct->m_Mode));
	CHECK_RESTRICTION(CHECK_CAN_SOURCE(canInitStruct->m_WorkSource));
	CHECK_RESTRICTION(CHECK_CAN_BAUDRATE_PRESET(canInitStruct->m_BaudRate));
	CHECK_RESTRICTION(CHECK_CAN_SYNC_JMP_WIDTH(canInitStruct->m_SyncJumpWidth));
	CHECK_RESTRICTION(CHECK_CAN_TIME_SEGMENT1(canInitStruct->m_TimeSeg1));
	CHECK_RESTRICTION(CHECK_CAN_TIME_SEGMENT2(canInitStruct->m_TimeSeg2));
	CHECK_RESTRICTION(CHECK_CAN_BUS_SAMPLE(canInitStruct->m_BusSample));

	/*---------------- ����CANx_CTLR�Ĵ��� ----------------*/
	/* ��ݽṹ���Աm_Enable������CANENλ�� */
	/* ��ݽṹ���Աm_Mode������LBACK��SILENTλ�� */
	/* ��ݽṹ���Աm_WorkSource������CANCKSλ�� */
	/* ����RSMOD�����븴λģʽ */
	tmpreg = ((uint32_t)canInitStruct->m_Enable << CAN_CTLR_CANEN_POS) \
		   | canInitStruct->m_Mode \
		   | canInitStruct->m_WorkSource \
		   | CAN_CTLR_RSMOD;
	CANx->CTLR = SFR_Config (CANx->CTLR, ~CAN_CTLR_INIT_MASK, tmpreg);

	CANx->CTLR |= (0x01<<12);
	/*---------------- ����CANx_BRGR�Ĵ��� ----------------*/
	/* ��ݽṹ���Աm_BaudRate������CANBRPλ�� */
	/* ��ݽṹ���Աm_SyncJumpWidth������SJWλ�� */
	/* ��ݽṹ���Աm_TimeSeg1������TSEG1λ�� */
	/* ��ݽṹ���Աm_TimeSeg2������TSEG2λ�� */
	/* ��ݽṹ���Աm_BusSample������SAMλ�� */
	tmpreg = ((uint32_t)canInitStruct->m_BaudRate << CAN_BRGR_CANBRP0_POS) \
		   | ((uint32_t)canInitStruct->m_SyncJumpWidth << CAN_BRGR_SJW0_POS) \
		   | ((uint32_t)canInitStruct->m_TimeSeg1 << CAN_BRGR_TSEG1_0_POS) \
		   | ((uint32_t)canInitStruct->m_TimeSeg2 << CAN_BRGR_TSEG2_0_POS) \
		   | (canInitStruct->m_BusSample);
	CANx->BRGR = SFR_Config (CANx->BRGR, ~CAN_BRGR_INIT_MASK, tmpreg);
	/* Enable Bus Off Hardware Recovery*/
	CANx->CTLR |= (0x01<<13);
	/* Enable Specific Filter */
	CANx->CTLR |= (0x01<<4);
	for(uint8_t filter_number = 0;filter_number<2;filter_number++)
	{
		if((canInitStruct->Filter_Group_Ptr+filter_number)->Frame_Type == Standard_Frame)
		{
			*(uint32_t *)Filter_Group_Address[filter_number] = ((canInitStruct->Filter_Group_Ptr+filter_number)->Acceptance_Code)<<21;
			*(uint32_t *)(Filter_Group_Address[filter_number]+4) = ((canInitStruct->Filter_Group_Ptr+filter_number)->Mask_Code)<<21;
			*(uint32_t *)(Filter_Group_Address[filter_number]+4) = ((canInitStruct->Filter_Group_Ptr+filter_number)->Mask_Code) |= 0x1FFFFF;
		}else if((canInitStruct->Filter_Group_Ptr+filter_number)->Frame_Type == Extended_Frame)
		{
			*(uint32_t *)Filter_Group_Address[filter_number] = ((canInitStruct->Filter_Group_Ptr+filter_number)->Acceptance_Code)<<3;
			*(uint32_t *)(Filter_Group_Address[filter_number]+4) = ((canInitStruct->Filter_Group_Ptr+filter_number)->Mask_Code)<<3;
			*(uint32_t *)(Filter_Group_Address[filter_number]+4) = ((canInitStruct->Filter_Group_Ptr+filter_number)->Mask_Code) |= 0x07;
		}
	}
	/* �˳���λģʽ */
	SFR_CLR_BIT_ASM(CANx->CTLR, CAN_CTLR_RSMOD_POS);
}

/**
 *  @brief :
 *  @param in :None
 *  @param out :None
 *  @retval :None
 */
RetStatus CAN_Transmit_Message_Once(volatile CAN_MessageTypeDef *CAN_Message)
{
		RetStatus ret = FAILURE;
		if (CAN_Message->m_DataLength > 8)
		{
			CAN_Message->m_DataLength = 8;
		}
		if ((!CAN_Get_Transmit_Status(CAN4_SFR, CAN_TX_BUFFER_STATUS)))
		{
			ret = FAILURE;
		}else
		{
			CAN4_SFR->CanTxBuffer.SFF.TXINFR.RTR = CAN_Message->m_RemoteTransmit;
			CAN4_SFR->CanTxBuffer.SFF.TXINFR.IDE = CAN_Message->m_FrameFormat;
			CAN4_SFR->CanTxBuffer.SFF.TXINFR.DLC = CAN_Message->m_DataLength;

			if(CAN_Message->m_FrameFormat == CAN_FRAME_FORMAT_SFF)
			{
				CAN4_SFR->CanTxBuffer.SFF.TXDATA0.ID =  CAN_Message->m_Can_ID;
				CAN4_SFR->CanTxBuffer.SFF.TXDATA0.DATA0 = CAN_Message->m_Data[0];
				CAN4_SFR->CanTxBuffer.SFF.TXDATA0.DATA1 = CAN_Message->m_Data[1];
				CAN4_SFR->CanTxBuffer.SFF.TXDATA1.DATA2 = CAN_Message->m_Data[2];
				CAN4_SFR->CanTxBuffer.SFF.TXDATA1.DATA3 = CAN_Message->m_Data[3];
				CAN4_SFR->CanTxBuffer.SFF.TXDATA1.DATA4 = CAN_Message->m_Data[4];
				CAN4_SFR->CanTxBuffer.SFF.TXDATA1.DATA5 = CAN_Message->m_Data[5];
				CAN4_SFR->CanTxBuffer.SFF.TXDATA2.DATA6 = CAN_Message->m_Data[6];
				CAN4_SFR->CanTxBuffer.SFF.TXDATA2.DATA7 = CAN_Message->m_Data[7];
			}else
			{
				CAN4_SFR->CanTxBuffer.EFF.TXDATA0.ID =  CAN_Message->m_Can_ID;
				CAN4_SFR->CanTxBuffer.EFF.TXDATA1.DATA0 = CAN_Message->m_Data[0];
				CAN4_SFR->CanTxBuffer.EFF.TXDATA1.DATA1 = CAN_Message->m_Data[1];
				CAN4_SFR->CanTxBuffer.EFF.TXDATA1.DATA2 = CAN_Message->m_Data[2];
				CAN4_SFR->CanTxBuffer.EFF.TXDATA1.DATA3 = CAN_Message->m_Data[3];
				CAN4_SFR->CanTxBuffer.EFF.TXDATA2.DATA4 = CAN_Message->m_Data[4];
				CAN4_SFR->CanTxBuffer.EFF.TXDATA2.DATA5 = CAN_Message->m_Data[5];
				CAN4_SFR->CanTxBuffer.EFF.TXDATA2.DATA6 = CAN_Message->m_Data[6];
				CAN4_SFR->CanTxBuffer.EFF.TXDATA2.DATA7 = CAN_Message->m_Data[7];
			}
			ret = CAN_Transmit_Single(CAN4_SFR);
		}
		return ret;
}



RetStatus CAN_Transmit_Message_Repeat(volatile CAN_MessageTypeDef *CAN_Message)
{
		RetStatus ret = FAILURE;
		if (CAN_Message->m_DataLength > 8)
		{
			CAN_Message->m_DataLength = 8;
		}
		if ((!CAN_Get_Transmit_Status(CAN4_SFR, CAN_TX_BUFFER_STATUS)))
		{
			ret = FAILURE;
		}else
		{
			CAN4_SFR->CanTxBuffer.SFF.TXINFR.RTR = CAN_Message->m_RemoteTransmit;
			CAN4_SFR->CanTxBuffer.SFF.TXINFR.IDE = CAN_Message->m_FrameFormat;
			CAN4_SFR->CanTxBuffer.SFF.TXINFR.DLC = CAN_Message->m_DataLength;

			if(CAN_Message->m_FrameFormat == CAN_FRAME_FORMAT_SFF)
			{
				CAN4_SFR->CanTxBuffer.SFF.TXDATA0.ID =  CAN_Message->m_Can_ID;
				CAN4_SFR->CanTxBuffer.SFF.TXDATA0.DATA0 = CAN_Message->m_Data[0];
				CAN4_SFR->CanTxBuffer.SFF.TXDATA0.DATA1 = CAN_Message->m_Data[1];
				CAN4_SFR->CanTxBuffer.SFF.TXDATA1.DATA2 = CAN_Message->m_Data[2];
				CAN4_SFR->CanTxBuffer.SFF.TXDATA1.DATA3 = CAN_Message->m_Data[3];
				CAN4_SFR->CanTxBuffer.SFF.TXDATA1.DATA4 = CAN_Message->m_Data[4];
				CAN4_SFR->CanTxBuffer.SFF.TXDATA1.DATA5 = CAN_Message->m_Data[5];
				CAN4_SFR->CanTxBuffer.SFF.TXDATA2.DATA6 = CAN_Message->m_Data[6];
				CAN4_SFR->CanTxBuffer.SFF.TXDATA2.DATA7 = CAN_Message->m_Data[7];
			}else
			{
				CAN4_SFR->CanTxBuffer.EFF.TXDATA0.ID =  CAN_Message->m_Can_ID;
				CAN4_SFR->CanTxBuffer.EFF.TXDATA1.DATA0 = CAN_Message->m_Data[0];
				CAN4_SFR->CanTxBuffer.EFF.TXDATA1.DATA1 = CAN_Message->m_Data[1];
				CAN4_SFR->CanTxBuffer.EFF.TXDATA1.DATA2 = CAN_Message->m_Data[2];
				CAN4_SFR->CanTxBuffer.EFF.TXDATA1.DATA3 = CAN_Message->m_Data[3];
				CAN4_SFR->CanTxBuffer.EFF.TXDATA2.DATA4 = CAN_Message->m_Data[4];
				CAN4_SFR->CanTxBuffer.EFF.TXDATA2.DATA5 = CAN_Message->m_Data[5];
				CAN4_SFR->CanTxBuffer.EFF.TXDATA2.DATA6 = CAN_Message->m_Data[6];
				CAN4_SFR->CanTxBuffer.EFF.TXDATA2.DATA7 = CAN_Message->m_Data[7];
			}
			ret = CAN_Transmit_Repeat(CAN4_SFR);
		}
		return ret;
}


/**
 *  @brief :
 *  @param in :None
 *  @param out :None
 *  @retval :None
 */
RetStatus CAN_Receive_Message(volatile Can_Pdu_TypeDef *Pdu)
{
	RetStatus ret;
	uint32_t tmpaddr = 0;
	uint8_t mailboxpoint =  CAN_Get_Point_Of_RAM_Mailbox(CAN4_SFR);
	uint8_t RmcCount = CAN_Get_Receive_Message_Counter(CAN4_SFR);
	int32_t ReceiveOffset = (mailboxpoint-RmcCount);
	if(ReceiveOffset>=0)
	{
		ReceiveOffset = ReceiveOffset*0x10;
	}else
	{
		ReceiveOffset = (ReceiveOffset+64)*0x10;
	}
	Pdu->Frame_length = RmcCount;
	for (uint8_t receive_count = 0; receive_count < RmcCount; receive_count++)
	{
		tmpaddr = CAN4_RECEIVE_ADDR;
		tmpaddr += ReceiveOffset;
		volatile CanRxBufferTypeDef *CanRxBufferPtr = (volatile CanRxBufferTypeDef *)tmpaddr;
		Pdu->CAN_Message[receive_count].m_FrameFormat = CanRxBufferPtr->SFF.RXDATA0.IDE;
		Pdu->CAN_Message[receive_count].m_DataLength = CanRxBufferPtr->SFF.RXDATA0.DLC;
		Pdu->CAN_Message[receive_count].m_RemoteTransmit = CanRxBufferPtr->SFF.RXDATA0.RTR;

		if(Pdu->CAN_Message[receive_count].m_RemoteTransmit == 0x01)
		{
			ReceiveOffset += 0x10;
			if (ReceiveOffset > 1008)
			{
				ReceiveOffset = 0;
			}
			continue;
		}else
		{
			Pdu->CAN_Message[receive_count].m_RemoteTransmit = CAN_DATA_FRAME;
		}
		if(Pdu->CAN_Message[receive_count].m_FrameFormat == 0x00)
		{
			/* Standard Frame Format  */
			Pdu->CAN_Message[receive_count].m_Can_ID = CanRxBufferPtr->SFF.RXDATA1.ID;
			Pdu->CAN_Message[receive_count].m_Data[0] = CanRxBufferPtr->SFF.RXDATA1.DATA0;
			Pdu->CAN_Message[receive_count].m_Data[1] = CanRxBufferPtr->SFF.RXDATA1.DATA1;
			Pdu->CAN_Message[receive_count].m_Data[2] = CanRxBufferPtr->SFF.RXDATA2.DATA2;
			Pdu->CAN_Message[receive_count].m_Data[3] = CanRxBufferPtr->SFF.RXDATA2.DATA3;
			Pdu->CAN_Message[receive_count].m_Data[4] = CanRxBufferPtr->SFF.RXDATA2.DATA4;
			Pdu->CAN_Message[receive_count].m_Data[5] = CanRxBufferPtr->SFF.RXDATA2.DATA5;
			Pdu->CAN_Message[receive_count].m_Data[6] = CanRxBufferPtr->SFF.RXDATA3.DATA6;
			Pdu->CAN_Message[receive_count].m_Data[7] = CanRxBufferPtr->SFF.RXDATA3.DATA7;
		}else
		{
			/* Extended Frame Format  */
			Pdu->CAN_Message[receive_count].m_Can_ID = CanRxBufferPtr->EFF.RXDATA1.ID;
			Pdu->CAN_Message[receive_count].m_Data[0] = CanRxBufferPtr->EFF.RXDATA2.DATA0;
			Pdu->CAN_Message[receive_count].m_Data[1] = CanRxBufferPtr->EFF.RXDATA2.DATA1;
			Pdu->CAN_Message[receive_count].m_Data[2] = CanRxBufferPtr->EFF.RXDATA2.DATA2;
			Pdu->CAN_Message[receive_count].m_Data[3] = CanRxBufferPtr->EFF.RXDATA2.DATA3;
			Pdu->CAN_Message[receive_count].m_Data[4] = CanRxBufferPtr->EFF.RXDATA3.DATA4;
			Pdu->CAN_Message[receive_count].m_Data[5] = CanRxBufferPtr->EFF.RXDATA3.DATA5;
			Pdu->CAN_Message[receive_count].m_Data[6] = CanRxBufferPtr->EFF.RXDATA3.DATA6;
			Pdu->CAN_Message[receive_count].m_Data[7] = CanRxBufferPtr->EFF.RXDATA3.DATA7;
		}
		ReceiveOffset += 0x10;
		if (ReceiveOffset > 1008)
		{
			ReceiveOffset = 0;
		}
	}
	CAN_Release_Receive_Buffer(CAN4_SFR, RmcCount);
	ret  = SUCCESS;
	return ret;
}


/**
 *  @brief :
 *  @param in :None
 *  @param out :None
 *  @retval :None
 */
void CAN_Int_Config(Can_Interrupt_Type *Can_Interrupt)
{
	if(Can_Interrupt->CAN_TRANSMIT_INTERRUPT == INTERRUPT_ENABLE)
	{
		CAN_Set_INT_Enable(CAN4_SFR,CAN_INT_TRANSMIT,TRUE);
	}

	if(Can_Interrupt->CAN_RECEIVE_INTERRUPT == INTERRUPT_ENABLE)
	{
		CAN_Set_INT_Enable(CAN4_SFR,CAN_INT_RECEIVE,TRUE);
	}

	if(Can_Interrupt->CAN_OVERFLOW_INTERRUPT == INTERRUPT_ENABLE)
	{
		CAN_Set_INT_Enable(CAN4_SFR,CAN_INT_DATA_OVERFLOW,TRUE);
	}

	if(Can_Interrupt->CAN_BUSERROR_INTERRUPT == INTERRUPT_ENABLE)
	{
		CAN_Set_INT_Enable(CAN4_SFR,CAN_INT_BUS_ERROR,TRUE);
	}

	if(Can_Interrupt->CAN_BUSOFF_INTERRUPT == INTERRUPT_ENABLE)
	{
		CAN_Set_INT_Enable(CAN4_SFR,CAN_INT_BUS_OFF,TRUE);
	}

	if(Can_Interrupt->CAN_ERRORNEGATIVE_INTERRUPT == INTERRUPT_ENABLE)
	{
		CAN_Set_INT_Enable(CAN4_SFR,CAN_INT_ERROR_NEGATIVE,TRUE);
	}
	INT_Interrupt_Enable(INT_CAN4,TRUE);
	INT_All_Enable(TRUE);
}

void CAN_Configuration(void)
{
	/* Initialize Can IOs
	 *     - PC10 = CAN4TX
	 *     - PC11 = CNA4RX
	 */
	CAN_Gpio_Init();
	/* Initialize Can Mode And Set Can Module To 500k baudrate*/
	CAN_Init(CAN4_SFR,&CAN_Condition);
	/* Initialize Can Interrupt */
	CAN_Int_Config(&Can_Interrupt);
}

/**
  * @brief  发送一帧CAN数据
  * @param  CANx CAN通道号
	* @param  TxMessage CAN消息指针
  * @retval 1-消息发送成功，0-消息发送失败
  */
uint8_t CAN_WriteData(uint8_t Channel,CAN_MSG *pMsg)
{
	Can_Pdu_TypeDef    Can_Pdu_Send = {
										{
											{
											CAN_FRAME_FORMAT_SFF,
											CAN_DATA_FRAME,
											8,
											pMsg->ID,
											{0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08},
											},
										},
										1,
									   };
	memcpy(Can_Pdu_Send.CAN_Message[0].m_Data,pMsg->Data,8);
	while(!CAN_Get_Transmit_Status(CAN4_SFR, CAN_TX_BUFFER_STATUS));
	RetStatus ret;
	do{
		ret = CAN_Transmit_Message_Once(&Can_Pdu_Send.CAN_Message[0]);
	}while(ret==FAILURE);
	//printf("TX[0x%03X]:%02X %02X %02X %02X %02X %02X %02X %02X\r\n",pMsg->ID,pMsg->Data[0],pMsg->Data[1],pMsg->Data[2],pMsg->Data[3],pMsg->Data[4],pMsg->Data[5],pMsg->Data[6],pMsg->Data[7]);
	//systick_delay_ms(5);
}
